package domain

import (
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/mars/pkg/errors"
)

// TicketType 入场券类型枚举
type TicketType string

const (
	TicketTypeFamilyFishing TicketType = "family_fishing_ticket" // 亲子垂钓券
	TicketTypeLureFishing   TicketType = "lure_fishing_ticket"   // 路亚钓鱼券
	TicketTypeForestYoga    TicketType = "forest_yoga_ticket"    // 森林瑜伽券
)

// PaginationParams 分页参数
type PaginationParams struct {
	Page     int `json:"page"`
	PageSize int `json:"pageSize"`
}

// DefaultPaginationParams 默认分页参数
var DefaultPaginationParams = PaginationParams{
	Page:     1,
	PageSize: 10,
}

// PaginationValidator 分页参数验证器
type PaginationValidator struct {
	MaxPageSize int
}

// NewPaginationValidator 创建分页验证器
func NewPaginationValidator(maxPageSize int) *PaginationValidator {
	if maxPageSize <= 0 {
		maxPageSize = 1000
	}
	return &PaginationValidator{
		MaxPageSize: maxPageSize,
	}
}

// ValidateAndParse 验证并解析分页参数
func (pv *PaginationValidator) ValidateAndParse(cxt *gin.Context) (PaginationParams, error) {
	pageStr := cxt.DefaultQuery("page", "1")
	sizeStr := cxt.DefaultQuery("size", "10")

	page, err := strconv.Atoi(pageStr)
	if err != nil || page < 1 {
		return PaginationParams{}, errors.New(http.StatusBadRequest, "invalid page parameter, must be a positive integer")
	}

	size, err := strconv.Atoi(sizeStr)
	if err != nil || size < 1 || size > pv.MaxPageSize {
		return PaginationParams{}, errors.New(http.StatusBadRequest,
			"invalid size parameter, must be between 1 and "+strconv.Itoa(pv.MaxPageSize))
	}

	return PaginationParams{
		Page:     page,
		PageSize: size,
	}, nil
}

// IDValidator ID验证器
type IDValidator struct {
	FieldName string
	MinLength int
	MaxLength int
}

// NewIDValidator 创建ID验证器
func NewIDValidator(fieldName string, minLength, maxLength int) *IDValidator {
	if minLength <= 0 {
		minLength = 1
	}
	if maxLength <= 0 {
		maxLength = 128
	}
	return &IDValidator{
		FieldName: fieldName,
		MinLength: minLength,
		MaxLength: maxLength,
	}
}

// ValidateFromParam 从路径参数验证ID
func (iv *IDValidator) ValidateFromParam(cxt *gin.Context, paramName string) (string, error) {
	id := cxt.Param(paramName)
	if id == "" {
		id = cxt.Query(paramName)
	}

	if id == "" {
		return "", errors.New(http.StatusBadRequest, iv.FieldName+" is required")
	}

	if len(id) < iv.MinLength || len(id) > iv.MaxLength {
		return "", errors.New(http.StatusBadRequest,
			iv.FieldName+" length must be between "+strconv.Itoa(iv.MinLength)+" and "+strconv.Itoa(iv.MaxLength)+" characters")
	}

	return id, nil
}

// DateValidator 日期验证器
type DateValidator struct{}

// NewDateValidator 创建日期验证器
func NewDateValidator() *DateValidator {
	return &DateValidator{}
}

// ValidateDate 验证日期格式并转换为时间戳
func (dv *DateValidator) ValidateDate(dateStr string) (*int64, error) {
	if dateStr == "" {
		return nil, nil
	}

	date, err := time.Parse("2006-01-02", dateStr)
	if err != nil {
		return nil, errors.New(http.StatusBadRequest, "invalid date format, must be YYYY-MM-DD")
	}

	timestamp := date.Unix()
	return &timestamp, nil
}

// ValidateDateRequired 验证必需的日期参数
func (dv *DateValidator) ValidateDateRequired(dateStr string) (int64, error) {
	if dateStr == "" {
		return 0, errors.New(http.StatusBadRequest, "date is required")
	}

	timestamp, err := dv.ValidateDate(dateStr)
	if err != nil {
		return 0, err
	}

	if timestamp == nil {
		return 0, errors.New(http.StatusBadRequest, "date is required")
	}

	return *timestamp, nil
}

// StringValidator 字符串验证器
type StringValidator struct {
	FieldName string
	MaxLength int
	Required  bool
}

// NewStringValidator 创建字符串验证器
func NewStringValidator(fieldName string, maxLength int, required bool) *StringValidator {
	return &StringValidator{
		FieldName: fieldName,
		MaxLength: maxLength,
		Required:  required,
	}
}

// Validate 验证字符串
func (sv *StringValidator) Validate(value string) error {
	if sv.Required && value == "" {
		return errors.New(http.StatusBadRequest, sv.FieldName+" is required")
	}

	if value != "" && sv.MaxLength > 0 && len(value) > sv.MaxLength {
		return errors.New(http.StatusBadRequest,
			sv.FieldName+" length must not exceed "+strconv.Itoa(sv.MaxLength)+" characters")
	}

	return nil
}

// EnumValidator 枚举验证器
type EnumValidator struct {
	FieldName   string
	ValidValues []string
	Required    bool
}

// NewEnumValidator 创建枚举验证器
func NewEnumValidator(fieldName string, validValues []string, required bool) *EnumValidator {
	return &EnumValidator{
		FieldName:   fieldName,
		ValidValues: validValues,
		Required:    required,
	}
}

// Validate 验证枚举值
func (ev *EnumValidator) Validate(value string) error {
	if ev.Required && value == "" {
		return errors.New(http.StatusBadRequest, ev.FieldName+" is required")
	}

	if value == "" && !ev.Required {
		return nil
	}

	for _, validValue := range ev.ValidValues {
		if value == validValue {
			return nil
		}
	}

	return errors.New(http.StatusBadRequest, ev.FieldName+" must be one of: "+joinStrings(ev.ValidValues, ", "))
}

// joinStrings 拼接字符串
func joinStrings(strs []string, sep string) string {
	if len(strs) == 0 {
		return ""
	}
	if len(strs) == 1 {
		return strs[0]
	}

	result := strs[0]
	for i := 1; i < len(strs); i++ {
		result += sep + strs[i]
	}
	return result
}

// SortParams 排序参数
type SortParams struct {
	Sort  string `json:"sort"`
	Order string `json:"order"`
}

// DefaultSortParams 默认排序参数
var DefaultSortParams = SortParams{
	Sort:  "createTime",
	Order: "desc",
}

// SortValidator 排序验证器
type SortValidator struct {
	ValidSortFields []string
	ValidOrders     []string
}

// NewSortValidator 创建排序验证器
func NewSortValidator(validSortFields []string) *SortValidator {
	if len(validSortFields) == 0 {
		validSortFields = []string{"createTime", "updateTime", "sort"}
	}
	return &SortValidator{
		ValidSortFields: validSortFields,
		ValidOrders:     []string{"asc", "desc"},
	}
}

// ValidateAndParse 验证并解析排序参数
func (sv *SortValidator) ValidateAndParse(cxt *gin.Context) (SortParams, error) {
	sort := cxt.DefaultQuery("sort", DefaultSortParams.Sort)
	order := cxt.DefaultQuery("order", DefaultSortParams.Order)

	// 验证排序字段
	validSort := false
	for _, validField := range sv.ValidSortFields {
		if sort == validField {
			validSort = true
			break
		}
	}
	if !validSort {
		return SortParams{}, errors.New(http.StatusBadRequest,
			"invalid sort field, must be one of: "+joinStrings(sv.ValidSortFields, ", "))
	}

	// 验证排序方向
	validOrder := false
	for _, validOrderValue := range sv.ValidOrders {
		if order == validOrderValue {
			validOrder = true
			break
		}
	}
	if !validOrder {
		return SortParams{}, errors.New(http.StatusBadRequest,
			"invalid order value, must be one of: "+joinStrings(sv.ValidOrders, ", "))
	}

	return SortParams{
		Sort:  sort,
		Order: order,
	}, nil
}
